]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
closeDialog: Untrack chrome when window loses focus
authorFlorian Müllner <fmuellner@gnome.org>
Tue, 4 Sep 2018 11:53:24 +0000 (13:53 +0200)
committerFlorian Müllner <florian.muellner@gmail.com>
Mon, 8 Oct 2018 16:03:53 +0000 (16:03 +0000)
On X11, reactive chrome must be added to the input region in order
to work as expected. However that region works independently from
any window stacking, with the result that the unresponsive-app dialog
currently blocks all input in the "covered" area, even in windows
stacked above the unresponsive window.

The correct fix would be to track the unobscured parts of the dialog
and set the input region from that, but that's quite cumbersome. So
instead, only track chrome when the corresponding window is focused
(or the dialog itself of course).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/273

js/ui/closeDialog.js

index 27e406434075d790775395bf46586b3ae9d26b65..2d019213ee80668dc60d85e5ddbff07c0e53f342 100644 (file)
@@ -28,7 +28,10 @@ var CloseDialog = new Lang.Class({
         this.parent();
         this._window = window;
         this._dialog = null;
+        this._tracked = undefined;
         this._timeoutId = 0;
+        this._windowFocusChangedId = 0;
+        this._keyFocusChangedId = 0;
     },
 
     get window() {
@@ -96,6 +99,37 @@ var CloseDialog = new Lang.Class({
         this.response(Meta.CloseDialogResponse.FORCE_CLOSE);
     },
 
+    _onFocusChanged() {
+        if (Meta.is_wayland_compositor())
+            return;
+
+        let focusWindow = global.display.focus_window;
+        let keyFocus = global.stage.key_focus;
+
+        let shouldTrack;
+        if (focusWindow != null)
+            shouldTrack = focusWindow == this._window;
+        else
+            shouldTrack = keyFocus && this._dialog.contains(keyFocus);
+
+        if (this._tracked === shouldTrack)
+            return;
+
+        if (shouldTrack)
+            Main.layoutManager.trackChrome(this._dialog,
+                                           { affectsInputRegion: true });
+        else
+            Main.layoutManager.untrackChrome(this._dialog);
+
+        // The buttons are broken when they aren't added to the input region,
+        // so disable them properly in that case
+        this._dialog.buttonLayout.get_children().forEach(b => {
+            b.reactive = shouldTrack;
+        });
+
+        this._tracked = shouldTrack;
+    },
+
     vfunc_show() {
         if (this._dialog != null)
             return;
@@ -108,6 +142,14 @@ var CloseDialog = new Lang.Class({
                 return GLib.SOURCE_CONTINUE;
             });
 
+        this._windowFocusChangedId =
+            global.display.connect('notify::focus-window',
+                                   this._onFocusChanged.bind(this));
+
+        this._keyFocusChangedId =
+            global.stage.connect('notify::key-focus',
+                                 this._onFocusChanged.bind(this));
+
         this._addWindowEffect();
         this._initDialog();
 
@@ -118,9 +160,7 @@ var CloseDialog = new Lang.Class({
                          { scale_y: 1,
                            transition: 'linear',
                            time: DIALOG_TRANSITION_TIME,
-                           onComplete: () => {
-                               Main.layoutManager.trackChrome(this._dialog, { affectsInputRegion: true });
-                           }
+                           onComplete: this._onFocusChanged.bind(this)
                          });
     },
 
@@ -133,6 +173,12 @@ var CloseDialog = new Lang.Class({
         GLib.source_remove(this._timeoutId);
         this._timeoutId = 0;
 
+        global.display.disconnect(this._windowFocusChangedId)
+        this._windowFocusChangedId = 0;
+
+        global.stage.disconnect(this._keyFocusChangedId);
+        this._keyFocusChangedId = 0;
+
         let dialog = this._dialog;
         this._dialog = null;
         this._removeWindowEffect();